package com.hjxr.quota.sdoc.controller;

import com.hjxr.quota.sdoc.domain.TChunkInfo;
import com.hjxr.quota.sdoc.domain.TFileInfo;
import com.hjxr.quota.sdoc.domain.TFileInfoVO;
import com.hjxr.quota.sdoc.domain.UploadResult;
import com.hjxr.quota.sdoc.service.ChunkService;
import com.hjxr.quota.sdoc.service.FileInfoService;
import com.hjxr.quota.sdoc.service.SdocColnameService;
import com.hjxr.quota.sdoc.service.SdocSevice;
import com.hjxr.quota.sdoc.util.FileInfoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/uploader")
public class FileController {


    @Resource
    private FileInfoService fileInfoService;
    @Resource
    private ChunkService chunkService;
    @Autowired
    private SdocSevice sdocSevice;
    @Autowired
    private SdocColnameService sdocColnameService;

    @Value("${hjxr.profile}")
    private String uploadFolder;

    @PostMapping("/chunk")
    public String uploadChunk(TChunkInfo chunkInfo) {
        String apiRlt = "200";
        MultipartFile upfile = chunkInfo.getUpfile();
        try {
            byte[] bytes = upfile.getBytes();
            Path path = Paths.get(FileInfoUtils.generatePath(uploadFolder, chunkInfo));
            Path write = Files.write(path, bytes);
            if (chunkService.saveChunk(chunkInfo) < 0) apiRlt = "415";
        } catch (IOException o) {
            o.printStackTrace();
            apiRlt = "415";
        }
        return apiRlt;
    }

    @GetMapping("/chunk")
    public UploadResult checkChunk(TChunkInfo chunk, HttpServletResponse response) {
        UploadResult ur = new UploadResult();

        //默认返回其他状态码，前端不进去checkChunkUploadedByResponse函数，正常走标准上传
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);

        String file = uploadFolder + "/" + chunk.getIdentifier() + "/" + chunk.getFilename();

        //先判断整个文件是否已经上传过了，如果是，则告诉前端跳过上传，实现秒传
        if (FileInfoUtils.fileExists(file)) {
            ur.setSkipUpload(true);
            ur.setLocation(file);
            response.setStatus(HttpServletResponse.SC_OK);
            ur.setMessage("完整文件已存在，直接跳过上传，实现秒传");
            return ur;
        }

        //如果完整文件不存在，则去数据库判断当前哪些文件块已经上传过了，把结果告诉前端，跳过这些文件块的上传，实现断点续传
        ArrayList<Integer> list = chunkService.checkChunk(chunk);
        if (list != null && list.size() > 0) {
            ur.setSkipUpload(false);
            ur.setUploadedChunks(list);
            response.setStatus(HttpServletResponse.SC_OK);
            ur.setMessage("部分文件块已存在，继续上传剩余文件块，实现断点续传");
            return ur;
        }
        return ur;
    }

    @PostMapping("/mergeFile")
    @Transactional(propagation = Propagation.REQUIRED)
    public String mergeFile(HttpServletRequest request, @RequestBody TFileInfoVO fileInfoVO) {

        String rlt = "FALURE";

        //前端组件参数转换为model对象
        TFileInfo fileInfo = new TFileInfo();
        fileInfo.setFilename(fileInfoVO.getName());
        fileInfo.setIdentifier(fileInfoVO.getUniqueIdentifier());
        fileInfo.setId(fileInfoVO.getId());
        fileInfo.setTotalSize(fileInfoVO.getSize());
        fileInfo.setRefProjectId(fileInfoVO.getRefProjectId());

        //进行文件的合并操作
        String filename = fileInfo.getFilename();
        String file = uploadFolder + "/" + fileInfo.getIdentifier() + "/" + filename;
        String folder = uploadFolder + "/" + fileInfo.getIdentifier();
        String fileSuccess = FileInfoUtils.merge(file, folder, filename);

        fileInfo.setLocation(file);

        //文件合并成功后，保存记录至数据库
        if ("200".equals(fileSuccess)) {
            if (fileInfoService.addFileInfo(fileInfo) > 0) {
                Integer num = sdocSevice.fileInformationToDb(fileInfo.getFilename(), fileInfo.getIdentifier()+"/"+filename, request);//插入返回id 失败为0
                sdocColnameService.fieldsInformationToDb(folder, filename, num, request);
                rlt = "SUCCESS";
            };
        }

        //如果已经存在，则判断是否同一个项目，同一个项目的不用新增记录，否则新增
        if ("300".equals(fileSuccess)) {
            List<TFileInfo> tfList = fileInfoService.selectFileByParams(fileInfo);
            if (tfList != null) {
                if (tfList.size() == 0 || (tfList.size() > 0 && !fileInfo.getRefProjectId().equals(tfList.get(0).getRefProjectId()))) {
                    if (fileInfoService.addFileInfo(fileInfo) > 0) rlt = "SUCCESS";
                }
            }
        }

        return rlt;
    }

    /**
     * 下载文件
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public void download(HttpServletRequest req, HttpServletResponse resp) {
        String location = req.getParameter("location");
        String fileName = req.getParameter("filename");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        OutputStream fos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(location));
            fos = resp.getOutputStream();
            bos = new BufferedOutputStream(fos);
            setFileDownloadHeader(req, resp, fileName);
            int byteRead = 0;
            byte[] buffer = new byte[8192];
            while ((byteRead = bis.read(buffer, 0, 8192)) != -1) {
                bos.write(buffer, 0, byteRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bos.flush();
                bis.close();
                fos.close();
                bos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 文件下载时用于写文件头部信息
     *
     * @param request  http请求
     * @param response http响应
     * @param fileName 文件名
     */
    public void setFileDownloadHeader(HttpServletRequest request,
                                      HttpServletResponse response, String fileName) {
        try {
            String encodedFileName = null;
            String agent = request.getHeader("USER-AGENT");
            if (null != agent && -1 != agent.indexOf("MSIE")) {
                encodedFileName = URLEncoder.encode(fileName, "UTF-8");
            } else if (null != agent && -1 != agent.indexOf("Mozilla")) {
                encodedFileName = new String(fileName.getBytes("UTF-8"),
                        "iso-8859-1");
            } else {
                encodedFileName = URLEncoder.encode(fileName, "UTF-8");
            }

//            response.setHeader("Content-Disposition", "attachment; filename=\""
//                    + encodedFileName + "\"");
            //response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Access-Control-Allow-Origin","*");
            response.setHeader("Access-Control-Allow-Credentials","true");
            response.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS");
            response.setHeader("Access-Control-Allow-Headers","DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type");
            response.setStatus(200);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
